#pragma once 
#include "protocol.hpp"
#include <pthread.h>

namespace ns_server
{
  class Server
  {
    private:
      uint16_t port;
      int listen_sock;
    public:
      Server(uint16_t _port): port(_port), listen_sock(-1)
      {}
      
      void InitServer()
      {
        listen_sock = socket(AF_INET, SOCK_STREAM, 0);
        if(listen_sock < 0)
        {
          std::cerr << "socket error" << std::endl;
          exit(2);
        }

        struct sockaddr_in local;
        bzero(&local, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(port);
        local.sin_addr.s_addr = INADDR_ANY;

        if(bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0)
        {
          std::cerr << "bind error" << std::endl;
          exit(3);
        }

        if(listen(listen_sock, 5) < 0)
        {
          std::cerr << "listen error" << std::endl;
          exit(4);
        }
      }

      static void *calc(void *args)
      {
        int sock = *(int*)args;
        delete (int*)args;

        while(true)
        {
          ns_protocol::Request req;
          ssize_t s = recv(sock, &req, sizeof(req), 0);
          //暂时省略了反序列化的一个过程
          if(s > 0)
          {
            ns_protocol::Response resp;
            switch(req.op)
            {
              case '+':
                resp.result = req.x + req.y;
                break;
              case '-':
                resp.result = req.x - req.y;
                break;
              case '*':
                resp.result = req.x * req.y;
                break;
              case '/':
                if(req.y == 0)  resp.code = 1;
                else  resp.result = req.x / req.y;
                break;
              case '%':
                if(req.y == 0)  resp.code = 2;
                else  resp.result = req.x % req.y;
                break;
              default:
                resp.code = 3;
                break;
            }
            //暂时省略了序列化的过程
            send(sock, &resp, sizeof(resp), 0);
          }
          else if(s == 0)
          {
            std::cout << "client quit...me too..." << std::endl;
            break;
          }
          else 
          {
            std::cerr << "recv error" << std::endl;
            break;
          }
        }
        close(sock);
        return nullptr;
      }

      void Loop()
      {
        while(true)
        {
          struct sockaddr_in peer;
          socklen_t len = sizeof(peer);
          int sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
          if(sock < 0)
          {
            std::cerr << "accept error" << std::endl;
            continue;
          }

          //handler sock 
          pthread_t tid;
          int *p = new int(sock);
          pthread_create(&tid, nullptr, calc, p);
        }
      }

      ~Server()
      {
        if(listen_sock >= 0)
        {
          close(listen_sock);
        }
      }
  };

}
